﻿Public Class Features

    Private Shared s_features As New Dictionary(Of Type, Feature)
    Private Shared s_repository As FeaturesRepository

    Public Shared Sub Register(Of T As Feature)(feature As T)
        s_features.Add(GetType(T), feature)
    End Sub

	Public Shared Sub Register(Of T As {Feature, New})()
		Register(Of T)(New T() With {.IsEnabled = False})
	End Sub
	
	Public Shared Sub RegisterIfNotExists(Of T As {Feature, New})()
		If Not Exists(Of T)() Then Register(Of T)()
	End Sub

	Public Shared Sub RegisterIfNotExists(Of T As {Feature, New})(feature As T)
		If Not Exists(Of T)() Then Register(Of T)(feature)
	End Sub

	Public Shared Function Exists(Of T As {Feature, New})() As Boolean
		Return s_features.ContainsKey(GetType(T))
	End Function

	Public Shared Sub Save()
		s_repository.SaveFeaturesState()
	End Sub

	Public Shared Function IsEnabled(Of T As Feature)() As Boolean
		Return IsEnabled(GetType(T))
	End Function

	Public Shared Sub Enable(Of T As Feature)()
		Dim feature = s_features(GetType(T))
		feature.IsEnabled = True
	End Sub

	Public Shared Sub Disable(Of T As Feature)()
		Dim feature = s_features(GetType(T))
		feature.IsEnabled = False
	End Sub

	Friend Shared Function IsEnabled(feature As Type) As Boolean
		If Not s_features.ContainsKey(feature) Then Return False

		Dim f = s_features(feature)
		Return f.IsEnabled
	End Function

	Public Shared Sub Initialize(repository As IFeaturesRepository)
		s_features.Clear()
		s_repository = New FeaturesRepository(repository)
		s_repository.LoadFeatures()
	End Sub

	Friend Shared Sub LoadSnapshot(snapshot As Dictionary(Of String, Boolean))
		If snapshot Is Nothing Then Return
		s_features.Clear()
		For Each fullname In snapshot.Keys
			Try
				Dim assemblyName = fullname.Split("|"c)(0)
				Dim typeName = fullname.Split("|"c)(1)
				Dim instance = CType(Activator.CreateInstance(assemblyName, typeName).Unwrap(), Feature)
				Dim type As Type = instance.GetType()
				instance.IsEnabled = snapshot(fullname)
				s_features.Add(type, instance)
			Catch ex As Exception
				'we don't care if features are no more defined in the application
			End Try
		Next
	End Sub

	Friend Shared Function GetSnapshot() As Dictionary(Of String, Boolean)
		Dim snapshot As New Dictionary(Of String, Boolean)
		For Each f In s_features.Keys
			Dim fullName As String = f.Assembly.FullName & "|" & f.FullName
			snapshot.Add(fullName, s_features(f).IsEnabled)
		Next
		Return snapshot
	End Function

End Class
